package animator.phantom.gui.timeline;

/*
    Copyright Janne Liljeblad 2006,2007,2008

    This file is part of Phantom2D.

    Phantom2D is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    Phantom2D is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with Phantom2D.  If not, see <http://www.gnu.org/licenses/>.
*/

import animator.phantom.controller.*;
import animator.phantom.gui.GUIResources;
import animator.phantom.gui.AnimFrameGUIParams;
import java.util.Hashtable;
import javax.swing.*;
import java.awt.*;
import javax.swing.event.*;

public class TimeLineSliders extends JPanel implements ChangeListener
{
	private int viewScale = 0;
	private int viewPosition = 0;

	private static final int SCALES_COUNT = TimeLineController.SCALES_COUNT;// number of possible display scales
	private static final int PIXELS_PER_FRAME_IN_MAX_SCALE = 40;

	public JSlider scaleSlider;
	private JSlider positionSlider;
	private JLabel scaleSmallLabel = new JLabel( GUIResources.getIcon( GUIResources.near ) );
	private JLabel scaleBigLabel = new JLabel( GUIResources.getIcon( GUIResources.far ) );
	private JLabel positionLabel = new JLabel( new ImageIcon() );

	//--- GUI parameters
	private static final int SCALE_WIDTH = 100;
	private static final int LABELS_WIDTH = 50;
	private static final int POSITION_WIDTH = 400;

	//--- Flags to stop infinete loops when values set by controllers.
	private boolean SCALE_SET_BY_PROGRAM = false;
	private boolean POS_SET_BY_PROGRAM = false;

	private boolean fromSource = false; 

	public TimeLineSliders()
	{
		//--- Create data for displaying different scales
		int columnWidth = AnimFrameGUIParams.getTimeEditRightColWidth();
	
		//--- Create GUI
		//--- Position slider, calculate max value first
		float pixelsPerFrame = TimeLineController.getCurrentScaleMultiplier();
		//---
		int framesInPanel = Math.round( columnWidth / pixelsPerFrame );
		int framesInMovie = ProjectController.getLength();
		int lastPos = framesInMovie - framesInPanel;
		//--- Create positionSlider
		positionSlider = new JSlider( JSlider.HORIZONTAL, 0, lastPos, 0 );
		positionSlider.addChangeListener(this);
		positionSlider.setSnapToTicks( true );
		positionSlider.setPaintTicks( false );
		positionSlider.setPaintLabels(false);
		positionSlider.setPreferredSize( 
			new Dimension( POSITION_WIDTH, AnimFrameGUIParams.TE_BOTTOM_STRIP_HEIGHT ) );
		positionSlider.setMaximumSize( 
			new Dimension( POSITION_WIDTH, AnimFrameGUIParams.TE_BOTTOM_STRIP_HEIGHT ) );

		calibratePositionSlider();

		//--- Scale slider
		scaleSlider = new JSlider(  0, SCALES_COUNT - 1, SCALES_COUNT - 1 );
		scaleSlider.addChangeListener( this );
		scaleSlider.setSnapToTicks( true );
        	Hashtable<Integer, JLabel> labelTable = new Hashtable<Integer, JLabel>();
		labelTable.put(new Integer( 0 ), new JLabel() );
	        scaleSlider.setLabelTable( labelTable);
		scaleSlider.setPaintLabels(true);
		scaleSlider.setPreferredSize( 
			new Dimension( SCALE_WIDTH, AnimFrameGUIParams.TE_BOTTOM_STRIP_HEIGHT ) );
		scaleSlider.setMaximumSize( 
			new Dimension( SCALE_WIDTH, AnimFrameGUIParams.TE_BOTTOM_STRIP_HEIGHT ) );

		//--- Put GUI together
		setLayout(new BoxLayout( this, BoxLayout.X_AXIS));
		add( scaleBigLabel  );
		add( scaleSlider );
		add( Box.createRigidArea( new Dimension( 20, 0 ) ) );
		add( scaleSmallLabel );
		add( positionSlider );
		add( Box.createHorizontalGlue() );
		setPreferredSize(new Dimension(columnWidth, AnimFrameGUIParams.TE_BOTTOM_STRIP_HEIGHT ));
	}

	//--- Bacause of change in viewable area size change when scale change
	//--- position of posion slider depens on scale too.
	public void calibratePositionSlider()
	{
		//--- Get needed data.
		float pixelsPerFrame = TimeLineController.getCurrentScaleMultiplier();
		int framesInPanel = 
			Math.round( AnimFrameGUIParams.getTimeEditRightColWidth() / pixelsPerFrame );
		int framesInMovie = ProjectController.getLength();

		//--- Calculate the frame that needs to be first to be displayed
		//--- so that movie's last frame still just fits in panel.
		int lastPos = framesInMovie - framesInPanel;
		
		//--- Calibrate position slider.
		positionSlider.setMaximum( lastPos );
		positionSlider.setMinimum( 0 );
		positionSlider.setValue( TimeLineController.getTimeLinePosition() );
	}
	//--- Position has been changed in other  TimeLineSliders 
	//------------------------------------------- INTERFACE
	public void posOrScaleChanged( int pos, int scale )
	{
		SCALE_SET_BY_PROGRAM = true;
		POS_SET_BY_PROGRAM = true;
		scaleSlider.setValue( scale );
		positionSlider.setValue( pos );
		calibratePositionSlider();
	}

	//------------------------------------------- GUI EVENT LISTENERS
	//--- Listen to the sliders.
	public void stateChanged(ChangeEvent e) 
	{
		JSlider source = (JSlider)e.getSource();

		//--- Handle scale changes
		if( source == scaleSlider )
		{
			//--- To kill infinite loop
			if( SCALE_SET_BY_PROGRAM )
				SCALE_SET_BY_PROGRAM = false;
			else
				UpdateController.updateTimeLineScale( scaleSlider.getValue(), this );
		}

		//--- Handle position changes.
		if( source == positionSlider )
		{
			//--- To kill infinite loop
			if( POS_SET_BY_PROGRAM )
				POS_SET_BY_PROGRAM = false;
			else
				UpdateController.updateTimeLinePosition( positionSlider.getValue(), this );
		}
	}

}//end class
